{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "___\n",
    "\n",
    "<a href='https://www.udemy.com/user/joseportilla/'><img src='../Pierian_Data_Logo.png'/></a>\n",
    "___\n",
    "<center><em>Content Copyright by Pierian Data</em></center>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# String Formatting\n",
    "\n",
    "String formatting lets you inject items into a string rather than trying to chain items together using commas or string concatenation. As a quick comparison, consider:\n",
    "\n",
    "    player = 'Thomas'\n",
    "    points = 33\n",
    "    \n",
    "    'Last night, '+player+' scored '+str(points)+' points.'  # concatenation\n",
    "    \n",
    "    f'Last night, {player} scored {points} points.'          # string formatting\n",
    "\n",
    "\n",
    "There are three ways to perform string formatting.\n",
    "* The oldest method involves placeholders using the modulo `%` character.\n",
    "* An improved technique uses the `.format()` string method.\n",
    "* The newest method, introduced with Python 3.6, uses formatted string literals, called *f-strings*.\n",
    "\n",
    "Since you will likely encounter all three versions in someone else's code, we describe each of them here."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Formatting with placeholders\n",
    "You can use <code>%s</code> to inject strings into your print statements. The modulo `%` is referred to as a \"string formatting operator\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I'm going to inject something here.\n"
     ]
    }
   ],
   "source": [
    "print(\"I'm going to inject %s here.\" %'something')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can pass multiple items by placing them inside a tuple after the `%` operator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I'm going to inject some text here, and more text here.\n"
     ]
    }
   ],
   "source": [
    "print(\"I'm going to inject %s text here, and %s text here.\" %('some','more'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also pass variable names:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I'm going to inject some text here, and more text here.\n"
     ]
    }
   ],
   "source": [
    "x, y = 'some', 'more'\n",
    "print(\"I'm going to inject %s text here, and %s text here.\"%(x,y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Format conversion methods.\n",
    "It should be noted that two methods <code>%s</code> and <code>%r</code> convert any python object to a string using two separate methods: `str()` and `repr()`. We will learn more about these functions later on in the course, but you should note that `%r` and `repr()` deliver the *string representation* of the object, including quotation marks and any escape characters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "He said his name was Fred.\n",
      "He said his name was 'Fred'.\n"
     ]
    }
   ],
   "source": [
    "print('He said his name was %s.' %'Fred')\n",
    "print('He said his name was %r.' %'Fred')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As another example, `\\t` inserts a tab into a string."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I once caught a fish this \tbig.\n",
      "I once caught a fish 'this \\tbig'.\n"
     ]
    }
   ],
   "source": [
    "print('I once caught a fish %s.' %'this \\tbig')\n",
    "print('I once caught a fish %r.' %'this \\tbig')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `%s` operator converts whatever it sees into a string, including integers and floats. The `%d` operator converts numbers to integers first, without rounding. Note the difference below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I wrote 3.75 programs today.\n",
      "I wrote 3 programs today.\n"
     ]
    }
   ],
   "source": [
    "print('I wrote %s programs today.' %3.75)\n",
    "print('I wrote %d programs today.' %3.75)   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Padding and Precision of Floating Point Numbers\n",
    "Floating point numbers use the format <code>%5.2f</code>. Here, <code>5</code> would be the minimum number of characters the string should contain; these may be padded with whitespace if the entire number does not have this many digits. Next to this, <code>.2f</code> stands for how many numbers to show past the decimal point. Let's see some examples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Floating point numbers: 13.14\n"
     ]
    }
   ],
   "source": [
    "print('Floating point numbers: %5.2f' %(13.144))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Floating point numbers: 13\n"
     ]
    }
   ],
   "source": [
    "print('Floating point numbers: %1.0f' %(13.144))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Floating point numbers: 13.14400\n"
     ]
    }
   ],
   "source": [
    "print('Floating point numbers: %1.5f' %(13.144))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Floating point numbers:      13.14\n"
     ]
    }
   ],
   "source": [
    "print('Floating point numbers: %10.2f' %(13.144))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Floating point numbers:                     13.14\n"
     ]
    }
   ],
   "source": [
    "print('Floating point numbers: %25.2f' %(13.144))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For more information on string formatting with placeholders visit https://docs.python.org/3/library/stdtypes.html#old-string-formatting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multiple Formatting\n",
    "Nothing prohibits using more than one conversion tool in the same print statement:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "First: hi!, Second:  3.14, Third: 'bye!'\n"
     ]
    }
   ],
   "source": [
    "print('First: %s, Second: %5.2f, Third: %r' %('hi!',3.1415,'bye!'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Formatting with the `.format()` method\n",
    "A better way to format objects into your strings for print statements is with the string `.format()` method. The syntax is:\n",
    "\n",
    "    'String here {} then also {}'.format('something1','something2')\n",
    "    \n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is a string with an insert\n"
     ]
    }
   ],
   "source": [
    "print('This is a string with an {}'.format('insert'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The .format() method has several advantages over the %s placeholder method:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1. Inserted objects can be called by index position:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The quick brown fox\n"
     ]
    }
   ],
   "source": [
    "print('The {2} {1} {0}'.format('fox','brown','quick'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. Inserted objects can be assigned keywords:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "First Object: 1, Second Object: Two, Third Object: 12.3\n"
     ]
    }
   ],
   "source": [
    "print('First Object: {a}, Second Object: {b}, Third Object: {c}'.format(a=1,b='Two',c=12.3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3. Inserted objects can be reused, avoiding duplication:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A penny saved is a penny earned.\n",
      "A penny saved is a penny earned.\n"
     ]
    }
   ],
   "source": [
    "print('A %s saved is a %s earned.' %('penny','penny'))\n",
    "# vs.\n",
    "print('A {p} saved is a {p} earned.'.format(p='penny'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Alignment, padding and precision with `.format()`\n",
    "Within the curly braces you can assign field lengths, left/right alignments, rounding parameters and more"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fruit    | Quantity \n",
      "Apples   |       3.0\n",
      "Oranges  |        10\n"
     ]
    }
   ],
   "source": [
    "print('{0:8} | {1:9}'.format('Fruit', 'Quantity'))\n",
    "print('{0:8} | {1:9}'.format('Apples', 3.))\n",
    "print('{0:8} | {1:9}'.format('Oranges', 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, `.format()` aligns text to the left, numbers to the right. You can pass an optional `<`,`^`, or `>` to set a left, center or right alignment:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Left     |  Center  |    Right\n",
      "11       |    22    |       33\n"
     ]
    }
   ],
   "source": [
    "print('{0:<8} | {1:^8} | {2:>8}'.format('Left','Center','Right'))\n",
    "print('{0:<8} | {1:^8} | {2:>8}'.format(11,22,33))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can precede the aligment operator with a padding character"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Left==== | -Center- | ...Right\n",
      "11====== | ---22--- | ......33\n"
     ]
    }
   ],
   "source": [
    "print('{0:=<8} | {1:-^8} | {2:.>8}'.format('Left','Center','Right'))\n",
    "print('{0:=<8} | {1:-^8} | {2:.>8}'.format(11,22,33))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Field widths and float precision are handled in a way similar to placeholders. The following two print statements are equivalent:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is my ten-character, two-decimal number:     13.58\n",
      "This is my ten-character, two-decimal number:     13.58\n"
     ]
    }
   ],
   "source": [
    "print('This is my ten-character, two-decimal number:%10.2f' %13.579)\n",
    "print('This is my ten-character, two-decimal number:{0:10.2f}'.format(13.579))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that there are 5 spaces following the colon, and 5 characters taken up by 13.58, for a total of ten characters.\n",
    "\n",
    "For more information on the string `.format()` method visit https://docs.python.org/3/library/string.html#formatstrings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Formatted String Literals (f-strings)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Introduced in Python 3.6, f-strings offer several benefits over the older `.format()` string method described above. For one, you can bring outside variables immediately into to the string rather than pass them as arguments through `.format(var)`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "He said his name is Fred.\n"
     ]
    }
   ],
   "source": [
    "name = 'Fred'\n",
    "\n",
    "print(f\"He said his name is {name}.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pass `!r` to get the string representation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "He said his name is 'Fred'\n"
     ]
    }
   ],
   "source": [
    "print(f\"He said his name is {name!r}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Float formatting follows `\"result: {value:{width}.{precision}}\"`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Where with the `.format()` method you might see `{value:10.4f}`, with f-strings this can become `{value:{10}.{6}}`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My 10 character, four decimal number is:   23.4568\n",
      "My 10 character, four decimal number is:   23.4568\n"
     ]
    }
   ],
   "source": [
    "num = 23.45678\n",
    "print(\"My 10 character, four decimal number is:{0:10.4f}\".format(num))\n",
    "print(f\"My 10 character, four decimal number is:{num:{10}.{6}}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that with f-strings, *precision* refers to the total number of digits, not just those following the decimal. This fits more closely with scientific notation and statistical analysis. Unfortunately, f-strings do not pad to the right of the decimal, even if precision allows it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My 10 character, four decimal number is:   23.4500\n",
      "My 10 character, four decimal number is:     23.45\n"
     ]
    }
   ],
   "source": [
    "num = 23.45\n",
    "print(\"My 10 character, four decimal number is:{0:10.4f}\".format(num))\n",
    "print(f\"My 10 character, four decimal number is:{num:{10}.{6}}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If this becomes important, you can always use `.format()` method syntax inside an f-string:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My 10 character, four decimal number is:   23.4500\n",
      "My 10 character, four decimal number is:   23.4500\n"
     ]
    }
   ],
   "source": [
    "num = 23.45\n",
    "print(\"My 10 character, four decimal number is:{0:10.4f}\".format(num))\n",
    "print(f\"My 10 character, four decimal number is:{num:10.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For more info on formatted string literals visit https://docs.python.org/3/reference/lexical_analysis.html#f-strings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That is the basics of string formatting!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
